home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FWSBP2Driver.c
-
- Contains: Sample SBP-2 driver
-
- Version: 1.0
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: Eric Anderson
-
- Other Contact:
-
- Technology: FireWire
-
- Writers:
-
- (EA) Eric Anderson (ewa)
- (DCB) Clinton Bauder
-
- Change History (most recent first):
-
- <FW14> 5/4/99 EA Added comment regarding driver name (sbp609e,104d8).
- <FW13> 5/4/99 EA Changed all DelayFor() to DelayForHardware(). DelayFor() can
- only be used at Task level and only for durations greater than
- 16 milliseconds.
- <FW12> 4/17/99 DCB Use offcial values for the name of the driver.
- <FW11> 1/10/99 EA Added support for testing cable power management API.
- <FW10> 1/3/99 EA Changed read block function to append dummy ORB, then a chain of
- ORBS, to test non-immediate append.
- <FW9> 1/3/99 EA Added (and commented out) a simple test of
- FWGetSBP2NormalCommandObjectIDFromORB_POINTER.
- <FW8> 1/1/99 EA Added test of FWGetFWReferenceIDFromUniqueID when we query
- logins. Also allocate memory for our ORB command object.
- <FW7> 12/31/98 EA Removed DebugStr that reported LUN status. Note that Query
- Logins doesn't report a timeout correctly yet.
- <FW6> 12/31/98 EA Added support for Query Logins.
- <FW5> 12/31/98 EA Added support for sending a TARGET RESET management ORB. Also
- set max payload size to 512 (now that FSL enforces it).
- <FW4> 11/18/98 EA Changed to report LUN.
- <FW3> 10/28/98 DCB Using new defs for matching SBP drivers. This allows us to be
- much more specific in our decision as to which driver belongs to
- which device.
- <FW2> 9/20/98 EA Filled in header comments.
- <FW1> 9/20/98 EA first checked in
- */
-
-
- #include <Types.h>
- #include <Errors.h>
- #include <Devices.h>
- #include <DriverServices.h>
- #include <FireWire.h>
- #include <FireWireSBP2.h>
- #include <SampleSBP2.h>
- #include <FWSBP2Driver.h>
- /*zzz*/
- #include <TextUtils.h>
- #include <stdio.h>
- char debugStr[256];
- /*zzz*/
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Internal procedure prototypes.
- //
-
- static OSStatus FWSBP2Initialize (
- RegEntryIDPtr pRegEntryID);
-
- static OSStatus FWSBP2Terminate (void);
-
- static OSStatus SBPDriverInterface (
- SBPInterfaceParamsPtr pSBPInterfaceParams);
-
- static OSStatus SBP2Login (
- SBPLoginParamsPtr pSBPLoginParams);
-
- static OSStatus SBP2Logout (
- SBPLogoutParamsPtr pSBPLogoutParams);
-
- static OSStatus SBP2Status (
- SBPStatusParamsPtr pSBPStatusParams);
-
- static OSStatus SBP2DoQueryLogins(
- SBPQueryLoginsParamsPtr pSBPQueryLoginsParams);
-
- static OSStatus SBP2DoStatusInquiry(
- SBPStatusInquiryParamsPtr pSBPStatusInquiryParams);
-
- static OSStatus SBP2DoModeSense(
- SBPModeSenseParamsPtr pSBPModeSenseParams);
-
- static OSStatus SBP2DoReadBlock(
- SBPReadBlockParamsPtr pSBPReadBlockParams);
-
- static OSStatus SBP2DoTargetReset(
- SBPTargetResetParamsPtr pSBPTargetResetParams);
-
- static OSStatus SBP2DoPowerTest(
- SBPPowerTestParamsPtr pSBPPowerTestParams);
-
- static OSStatus SBPLoginNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus SBPStatusNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus SBPUnsolicitedStatusNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance);
-
- #if 0
- static void SBP2ClientCommandCompletionProc (
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData);
- #endif
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // The driver descriptor.
- //
-
- // The driver name sbp609e,104d8 causes this driver to match against
- // a device that encapsulate SCSI as per section D.2 of the SBP-2
- // standard. Other driver names would be perfectly valid too, and
- // there is no requirement to use SCSI. This generic driver can log
- // in and out of any SBP-2 device. Some of the other commands in the
- // demo application are specific to RBC and 609e,104d8.
-
- DriverDescription TheDriverDescription =
- {
- kTheDescriptionSignature,
- kInitialDriverDescriptor,
- {
- "\psbp609e,104d8", // Encapsulated SCSI device per SBP2
- 1, 0, finalStage, 1,
- },
- {
- kDriverIsUnderExpertControl,
- "\p.FWSBP2Driver",
- },
-
- 1,
- kServiceCategoryNdrvDriver,
- kNdrvTypeIsSampleSBP2,
- 1,0,0,0
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // A quick note on how this works:
- //
- // The SBP2Expert creates sub-nodes for each LUN
- // ...:firewire:fw609e,10483
- // ...:firewire:fw609e,10483:sbpXXXXXX,YYYYYY
- // ...:firewire:fw609e,10483:sbpPPPPPP,QQQQQQ
- //
- // XXXXXX is the command_set_spec_ID of lun 0. YYYYYY is the command_set of lun 0.
- // PPPPPP is the command_set_spec_ID if lun 1. QQQQQQ is the command_set of lun 1. etc.
- //
- // The name of the driver then should match the sub-node created by the expert. To further
- // narrow down the match the SBP2Expert creates a table with the VendorID, SoftwareRev,
- // FirmwareRev, LUN and device_type values from the CSR ROM. This table is contained in
- // a property called "TheDFMTable". The format for this table is in FireWireSBP2.h.
- // A similar table is exported by the driver and is called TheDFMDescriptor. It is exactly
- // twice the size of TheDFMTable as it contains a range for each value exported by the expert.
- // Drivers which match the greatest number of values in the table are selected to match the
- // device. Fields with a negative range are marked as "don't care".
- //
- // Note that "don't care" is different from matching everything. Matching everything means
- // the score for the driver will be incremented for that field while don't care means that
- // it won't be. Thus a driver with 3 matches and 1 don't care scores lower than a driver
- // with 4 matches - even if the matches are the 0 through 0xFFFFFFFF type.
- //
- // Drivers with identical scores will be ranked by version as with other native drivers.
-
- SBPMatchData TheDFMDescriptor =
- {
- 0xFFFFFFFF, 0x00000000, // VendorID, match all (only low 24 bits valid)
- 0xFFFFFFFF, 0x00000000, // SoftwareRev, match all (only low 24 bits valid)
- 0xFFFFFFFF, 0x00000000, // FirmwareRev, match all (indicated by negative range)
- 0xFFFFFFFF, 0x00000000, // LUN, match all (only low 16 bits valid)
- 0xFFFFFFFF, 0x00000000 // device_type, match all (only low 5 bits valid)
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Global driver data.
- //
-
- FWSBP2DriverDataPtr gpFWSBP2DriverData = nil;
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // DoDriverIO
- //
- // Main entry point.
- //
-
- OSErr DoDriverIO(
- AddressSpaceID addressSpaceID,
- IOCommandID ioCommandID,
- IOCommandContents ioCommandContents,
- IOCommandCode ioCommandCode,
- IOCommandKind ioCommandKind)
- {
- CntrlParamPtr pCntrlParam;
- OSErr err = noErr;
-
- switch (ioCommandCode)
- {
- case kInitializeCommand :
- err = FWSBP2Initialize (&ioCommandContents.initialInfo->deviceEntry);
- break;
-
- case kFinalizeCommand :
- err = FWSBP2Terminate ();
-
- case kOpenCommand :
- break;
-
- case kCloseCommand :
- break; //zzz should probably do a logout
-
- case kControlCommand :
- pCntrlParam = (CntrlParamPtr) ioCommandContents.pb;
- if (pCntrlParam->csCode == cscSBPCommand)
- {
- err = SBPDriverInterface
- (*((SBPInterfaceParamsPtr *) &(pCntrlParam->csParam[0])));
- }
- else
- {
- err = controlErr;
- }
- break;
-
- case kStatusCommand :
- err = statusErr;
- break;
-
- default :
- err = paramErr;
- }
-
- // We're complete.
- if (ioCommandKind == kImmediateIOCommandKind)
- return (err);
- else
- return (IOCommandIsComplete (ioCommandID, err));
-
- return (err);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBPDriverInterface
- //
- // Main driver interface.
- //
-
- static OSStatus SBPDriverInterface(
- SBPInterfaceParamsPtr pSBPInterfaceParams)
- {
- UInt32 interfaceSelector;
- OSStatus status = noErr;
-
- // Get some params.
- interfaceSelector = pSBPInterfaceParams->interfaceSelector;
-
- // Note - most real SBP-2 drivers would not have these dispatches.
- // A disk driver would have open, close, read, write - etc. The
- // driver would decide when to perform a login, mode sense, etc.,
- // without being told to do these specific things.
-
- // Main dispatch.
- switch (interfaceSelector)
- {
- case kSampleSBPLogin :
- status = SBP2Login ((SBPLoginParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPLogout :
- status = SBP2Logout ((SBPLogoutParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPStatus :
- status = SBP2Status ((SBPStatusParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPQueryLogins :
- status = SBP2DoQueryLogins ((SBPQueryLoginsParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPStatusInquiry :
- status = SBP2DoStatusInquiry ((SBPStatusInquiryParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPModeSense :
- status = SBP2DoModeSense ((SBPModeSenseParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPReadBlock :
- status = SBP2DoReadBlock ((SBPReadBlockParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPTargetReset :
- status = SBP2DoTargetReset ((SBPTargetResetParamsPtr) pSBPInterfaceParams);
- break;
-
- case kSampleSBPPowerTest :
- status = SBP2DoPowerTest ((SBPPowerTestParamsPtr) pSBPInterfaceParams);
- break;
-
- default :
- status = paramErr;
- break;
- }
-
- return (status);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWSBP2Initialize
- //
- // This routine initializes the FireWire SBP2 sample driver. It
- // allocates a private data record and registers with the FireWire family.
- // It also prepares some command objects for use later on.
- //
-
- static OSStatus SBPLoginNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus FWSBP2Initialize(
- RegEntryIDPtr pRegEntryID)
- {
- FWSBP2DriverDataPtr pFWSBP2DriverData = nil;
- FWDriverID fwDriverID;
- OSStatus status = noErr;
-
- // Allocate our driver data.
- pFWSBP2DriverData =
- (FWSBP2DriverDataPtr) PoolAllocateResident (sizeof (FWSBP2DriverData), true);
- if (pFWSBP2DriverData == nil)
- {
- status = memFullErr;
- }
-
- // Register with the FireWire family.
- if (status == noErr)
- {
- status = FWRegisterDriver (pRegEntryID,
- &fwDriverID,
- &(pFWSBP2DriverData->csrUnitID),
- (UInt32) pFWSBP2DriverData);
-
- if (status == noErr)
- pFWSBP2DriverData->fwDriverID = fwDriverID;
- }
-
- // Get reference to local node.
- if (status == noErr)
- {
- status = FWGetLocalFWReferenceIDFromFWReferenceID
- (pFWSBP2DriverData->fwDriverID,
- &(pFWSBP2DriverData->localFWReferenceID));
- }
-
- // Set the maximum packet payload size.
- if (status == noErr)
- {
- status = FWSetMaxPayloadSize ((FWReferenceID) pFWSBP2DriverData->fwDriverID, 512);
- }
-
- // Allocate login command object.
- if (status == noErr)
- {
- status = FWAllocateSBP2LoginCommandObject ((FWReferenceID) pFWSBP2DriverData->fwDriverID,
- &pFWSBP2DriverData->loginCommandID);
- }
-
- if (status != noErr) pFWSBP2DriverData->loginCommandID = 0;
-
- // Prepare login command object.
- if (status == noErr)
- status = FWSetFWCommandFlags (pFWSBP2DriverData->loginCommandID, kFWCommandSyncFlag);
-
- if (status == noErr)
- {
- status = FWSetSBP2LoginCommandFlags (pFWSBP2DriverData->loginCommandID,
- kSBP2NotifyOnLoginComplete |
- kSBP2NotifyOnLoginFailed |
- kSBP2NotifyOnReconnecting |
- kSBP2NotifyOnReconnectComplete |
- kSBP2NotifyOnReconnectFailed);
- }
-
- if (status == noErr)
- {
- status = FWSetSBP2LoginCommandMaxPayloadSize (pFWSBP2DriverData->loginCommandID, 512);
- }
-
- if (status == noErr)
- {
- status = FWSetSBP2LoginCommandLoginNotifyProc (pFWSBP2DriverData->loginCommandID,
- SBPLoginNotify,
- (UInt32) pFWSBP2DriverData);
- }
-
- if (status == noErr)
- {
- status = FWSetSBP2LoginCommandStatusNotifyProc (pFWSBP2DriverData->loginCommandID,
- SBPStatusNotify,
- (UInt32) pFWSBP2DriverData);
- }
-
- if (status == noErr)
- {
- status = FWSetSBP2LoginCommandUnsolicitedStatusNotifyProc (pFWSBP2DriverData->loginCommandID,
- SBPUnsolicitedStatusNotify,
- (UInt32) pFWSBP2DriverData);
- }
-
- // Allocate a dummy ORB command object.
- if (status == noErr)
- {
- status = FWAllocateSBP2NormalCommandObject (pFWSBP2DriverData->loginCommandID,
- &pFWSBP2DriverData->dummyOrbID);
- }
-
- if (status != noErr) pFWSBP2DriverData->dummyOrbID = 0;
-
- if (status == noErr)
- status = FWAllocateFWCommandObjectMemory (pFWSBP2DriverData->dummyOrbID, 3 * 4096);
-
- // Allocate an ORB command object.
- if (status == noErr)
- {
- status = FWAllocateSBP2NormalCommandObject (pFWSBP2DriverData->loginCommandID,
- &pFWSBP2DriverData->firstOrbID);
- }
-
- if (status != noErr) pFWSBP2DriverData->firstOrbID = 0;
-
- if (status == noErr)
- status = FWAllocateFWCommandObjectMemory (pFWSBP2DriverData->firstOrbID, 3 * 4096);
-
- // Allocate another ORB command object.
- if (status == noErr)
- {
- status = FWAllocateSBP2NormalCommandObject (pFWSBP2DriverData->loginCommandID,
- &pFWSBP2DriverData->orbID);
- }
-
- if (status != noErr) pFWSBP2DriverData->orbID = 0;
-
- if (status == noErr)
- status = FWAllocateFWCommandObjectMemory (pFWSBP2DriverData->orbID, 3 * 4096);
-
- // Allocate a management ORB command object.
- if (status == noErr)
- {
- status = FWAllocateSBP2ManagementCommandObject ((FWReferenceID) pFWSBP2DriverData->fwDriverID,
- &pFWSBP2DriverData->managementORBID);
- }
-
- if (status != noErr) pFWSBP2DriverData->managementORBID = 0;
-
- // Allocate an asynch command object for writing to the AGENT_RESET register.
- if (status == noErr)
- {
- status = FWAllocateAsynchCommandObject (&pFWSBP2DriverData->fwAGENT_RESET_ID);
- }
-
- if (status == noErr)
- {
- status = FWSetFWCommandParams (pFWSBP2DriverData->fwAGENT_RESET_ID,
- pFWSBP2DriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- }
-
- // The AGENT_RESET command object will be filled in some more after we get the
- // login response and we learn the address of the fetch agent.
-
- // Allocate an asynch command object for writing to the DOORBELL register.
- if (status == noErr)
- {
- status = FWAllocateAsynchCommandObject (&pFWSBP2DriverData->fwDOORBELL_ID);
- }
-
- if (status == noErr)
- {
- status = FWSetFWCommandParams (pFWSBP2DriverData->fwDOORBELL_ID,
- pFWSBP2DriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- }
-
- // The DOORBELL command object will be filled in some more after we get the
- // login response and we learn the address of the fetch agent.
-
- // Allocate an asynch command object for reading the ORB_POINTER register.
- if (status == noErr)
- {
- status = FWAllocateAsynchCommandObject (&pFWSBP2DriverData->readORB_POINTER_ID);
- }
-
- if (status == noErr)
- {
- status = FWSetFWCommandParams (pFWSBP2DriverData->readORB_POINTER_ID,
- pFWSBP2DriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- }
-
- // Allocate a Cable Power Management command object
- if (status == noErr)
- {
- status = FWAllocatePowerCommandObject (&pFWSBP2DriverData->powerChangeID);
- }
-
- if (status == noErr)
- {
- status = FWSetFWCommandParams (pFWSBP2DriverData->powerChangeID,
- pFWSBP2DriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- }
-
- if (status == noErr)
- {
- pFWSBP2DriverData->notificationMessage = PoolAllocateResident (1024, true);
- if (!pFWSBP2DriverData->notificationMessage)
- status = memFullErr;
- }
-
- // Make a note of our LUN
- if (status == noErr)
- {
- status = FWGetSBP2LUNFromFWReferenceID (pFWSBP2DriverData->fwDriverID,
- &pFWSBP2DriverData->lun);
-
- //sprintf (debugStr, "Driver get status %ld lun %ld",
- // (long) status, (long) pFWSBP2DriverData->lun);
- //DebugStr ((ConstStr255Param) c2pstr (debugStr));
-
- }
-
- // Save our driver data or clean up on error.
- if (status == noErr)
- {
- gpFWSBP2DriverData = pFWSBP2DriverData;
- }
- else
- {//zzz should use terminate
- if (pFWSBP2DriverData != nil)
- PoolDeallocate ((Ptr) pFWSBP2DriverData);
- }
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWSBP2Terminate
- //
- // This routine terminates the FireWire SBP2 sample driver. It
- // deallocates a private data record and unregisters with the FireWire family.
- //
- // Note, with the sample family and app, this routine is never called.
- // Even if you unplug the device, nobody terminates the driver.
- //
-
- static OSStatus FWSBP2Terminate(void)
- {
- OSStatus status = noErr;
-
- if (gpFWSBP2DriverData != nil)
- {
- // Unregister with FireWire family.
- if (gpFWSBP2DriverData->fwDriverID != kInvalidFWDriverID)
- FWUnregisterDriver (gpFWSBP2DriverData->fwDriverID);
-
- //zzz We should check that ORB is not active before we deallocate it.
- // We could issue a target reset to guarantee this.
-
- if (gpFWSBP2DriverData->orbID)
- FWDeallocateFWCommandObject (gpFWSBP2DriverData->orbID);
-
- if (gpFWSBP2DriverData->login)
- FWSBP2Logout (gpFWSBP2DriverData->loginCommandID);
-
- if (gpFWSBP2DriverData->loginCommandID)
- FWDeallocateFWCommandObject (gpFWSBP2DriverData->loginCommandID);
-
- // Deallocate our driver data.
- PoolDeallocate ((Ptr) gpFWSBP2DriverData);
- gpFWSBP2DriverData = nil;
- }
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2Login
- //
- // This routine performs a login.
- //
-
- static OSStatus SBP2Login(
- SBPLoginParamsPtr pSBPLoginParams)
- {
- OSStatus status = noErr;
-
- gpFWSBP2DriverData->reconnectFailed = false;
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
-
- status = FWSBP2Login (gpFWSBP2DriverData->loginCommandID);
- pSBPLoginParams->status = status;
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2Logout
- //
- // This routine performs a logout.
- //
-
- static OSStatus SBP2Logout(
- SBPLogoutParamsPtr pSBPLogoutParams)
- {
- OSStatus status = noErr;
-
- status = FWSBP2Logout (gpFWSBP2DriverData->loginCommandID);
- pSBPLogoutParams->status = status;
-
- if (status == noErr) gpFWSBP2DriverData->login = false;
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2Status
- //
- // This routine returns various status.
- //
-
- static OSStatus SBP2Status(
- SBPStatusParamsPtr pSBPStatusParams)
- {
- OSStatus status = noErr;
-
- pSBPStatusParams->login = gpFWSBP2DriverData->login;
- pSBPStatusParams->reconnecting = gpFWSBP2DriverData->reconnecting;
- pSBPStatusParams->reconnectFailed = gpFWSBP2DriverData->reconnectFailed;
-
- pSBPStatusParams->notificationCounter = gpFWSBP2DriverData->notificationCounter;
- pSBPStatusParams->notificationEvent = gpFWSBP2DriverData->notificationEvent;
- pSBPStatusParams->notificationLength = gpFWSBP2DriverData->notificationLength;
-
- //zzz Driver should not share it's pointer with application. Should copy buffer instead.
- pSBPStatusParams->notificationMessage = gpFWSBP2DriverData->notificationMessage;
-
- pSBPStatusParams->lun = gpFWSBP2DriverData->lun;
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoQueryLogins
- //
- // This routine sends a Query Logins management ORB.
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoQueryLogins(
- SBPQueryLoginsParamsPtr pSBPQueryLoginsParams)
- {
- FWCommandObjectID orbID;
- CSRNodeUniqueID uniqueID;
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- orbID = gpFWSBP2DriverData->managementORBID;
-
- if (status == noErr)
- status = FWSetSBP2ManagementCommandFunction (orbID, kSBP2QueryLogins);
-
- if (status == noErr)
- status = FWSetSBP2ManagementCommandResponseBuffer (orbID, (Ptr) pSBPQueryLoginsParams->response, 256);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (orbID, kFWCommandSyncFlag);
-
- if (status == noErr)
- status = FWSBP2Manage (orbID);
-
- // The Manage command was synchronous. When it returns, the command has been
- // sent to the target and the target has executed the command.
-
- // Using the first EUI-64 returned (if any), test FWGetFWReferenceIDFromUniqueID
- // to see if it returns the corresponsing fwReferenceID, or an error if the ID is
- // invalid (and thus not found).
-
- if (status == noErr)
- {
- uniqueID.hi = pSBPQueryLoginsParams->response[2];
- uniqueID.lo = pSBPQueryLoginsParams->response[3];
- pSBPQueryLoginsParams->uniqueIDStatus =
- FWGetFWReferenceIDFromUniqueID (gpFWSBP2DriverData->fwDriverID,
- uniqueID,
- &pSBPQueryLoginsParams->fwReferenceID);
-
- if (pSBPQueryLoginsParams->uniqueIDStatus == noErr)
- status = FWGetUniqueID (pSBPQueryLoginsParams->fwReferenceID,
- &pSBPQueryLoginsParams->uniqueID);
- }
-
- pSBPQueryLoginsParams->status = status;
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoStatusInquiry
- //
- // This routine performs a status inquiry. With the Symbios SYMFW2500 kit,
- // a status inquiry will clear a check condition and allow the drive to be used.
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoStatusInquiry(
- SBPStatusInquiryParamsPtr pSBPStatusInquiryParams)
- {
- FWCommandObjectID orbID;
- FWAddress buffers[1];
- UInt32 lengths[1];
- char buffer[256];
- UInt8 command[12] = {0x03, 0, 0, 0, 0x12, 0, 0, 0, 0, 0, 0, 0};
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- orbID = gpFWSBP2DriverData->orbID;
-
- // Prepare the ORB.
-
- buffers[0].addressHi = 0;
- buffers[0].addressLo = (UInt32) buffer;
- lengths[0] = 18;
- status = FWSetSBP2NormalCommandBuffers (orbID, 1, buffers, lengths);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandCommand (orbID, (Ptr) command, 12);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandTimeout (orbID, durationMillisecond * 1000);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandFlags (orbID,
- kSBP2CommandTransferDataFromTarget |
- kSBP2CommandImmediate |
- kSBP2CommandCompleteNotify);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (orbID, kFWCommandSyncFlag);
-
- if (status == noErr)
- status = FWAppendSBP2Command (orbID);
-
- // The Append command was synchronous. When it returns, the command has been
- // appended to the target. But the target probably has not executed the command yet.
-
- if (status == noErr)
- {
- //zzz Just wait for target to execute command. Should use notification instead.
- DelayForHardware (DurationToAbsolute (durationMillisecond * 1000));
- //should have response by now
- }
-
- // After a Status Inquiry, the SYM13FW2500 will be in the Dead state, so we
- // need to reset the Fetch Agent.
- if (status == noErr)
- status = FWWrite (gpFWSBP2DriverData->fwAGENT_RESET_ID);
-
- // "buffer" was allocated on the stack. So it would be very bad to return
- // now if the ORB was still active.
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoModeSense
- //
- // This routine performs a mode sense. With the Symbios SYMFW2500 kit,
- // a mode sense will return some data about the drive that is connected.
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoModeSense(
- SBPModeSenseParamsPtr pSBPModeSenseParams)
- {
- FWCommandObjectID orbID;
- FWAddress buffers[1];
- UInt32 lengths[1];
- char buffer[256];
- UInt8 command[12] = {0x5a, 0x08, 0x3e, 0, 0, 0, 0, 0, 0xff, 0, 0, 0};
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- orbID = gpFWSBP2DriverData->orbID;
-
- // Prepare the ORB.
-
- buffers[0].addressHi = 0;
- buffers[0].addressLo = (UInt32) buffer;
- lengths[0] = 255;
- status = FWSetSBP2NormalCommandBuffers (orbID, 1, buffers, lengths);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandCommand (orbID, (Ptr) command, 12);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandTimeout (orbID, durationMillisecond * 1000);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandFlags (orbID,
- kSBP2CommandTransferDataFromTarget |
- kSBP2CommandImmediate);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (orbID, kFWCommandSyncFlag);
-
- if (status == noErr)
- status = FWAppendSBP2Command (orbID);
-
- // The Append command was synchronous. When it returns, the command has been
- // appended to the target. But the target probably has not executed the command yet.
-
- if (status == noErr)
- {
- //zzz Just wait for target to execute command. Should use notification instead.
- DelayForHardware (DurationToAbsolute (durationMillisecond * 1000));
- //should have response by now
- }
-
- // My SYM13FW2500 does not understand the page_table_present bit, so the
- // mode sense does not work (in fact, it tries to write the result onto
- // the page table!)
-
- // "buffer" was allocated on the stack. So it would be very bad to return
- // now if the ORB was still active.
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoReadBlock
- //
- // This routine reads block zero, assuming the target is a simple hard drive.
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoReadBlock(
- SBPReadBlockParamsPtr pSBPReadBlockParams)
- {
- FWCommandObjectID orbID, dummyOrbID, firstOrbID;
- FWAddress buffers[1];
- UInt32 lengths[1];
- char buffer[4096];
- UInt8 command[12];
- UInt32 lba = 0;
- UInt16 xfer = 1;
- UInt32 transferIsWrite = 0;
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- dummyOrbID = gpFWSBP2DriverData->dummyOrbID;
- firstOrbID = gpFWSBP2DriverData->firstOrbID;
- orbID = gpFWSBP2DriverData->orbID;
-
- // Prepare a dummy ORB.
- status = FWSetSBP2NormalCommandBuffers (dummyOrbID, 0, 0, 0);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandFlags (dummyOrbID, kSBP2CommandDummyORB | kSBP2CommandImmediate);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (dummyOrbID, kFWCommandSyncFlag);
-
- // We're actually going to read two blocks, to see if ORB chaining works.
-
- // Prepare first ORB.
- // Page table total length must agree with ATAPI request length, or drive
- // will get confused.
-
- buffers[0].addressHi = 0;
- buffers[0].addressLo = (UInt32) buffer;
- lengths[0] = 512;
- if (status == noErr)
- status = FWSetSBP2NormalCommandBuffers (firstOrbID, 1, buffers, lengths);
-
- // Form ATAPI command (SCSI-3, cribbed from MMC-2 spec)
- command[0] = (transferIsWrite ? 0x2A : 0x28); // Write or Read
- command[1] = 0; // Mostly reserved
- command[2] = (lba >> 24) & 0xff; // MSB of LBA
- command[3] = (lba >> 16) & 0xff;
- command[4] = (lba >> 8) & 0xff;
- command[5] = lba & 0xff; // LSB of LBA
- command[6] = 0; // Reserved
- command[7] = (xfer >> 8) & 0xff; // MSB of block count
- command[8] = xfer & 0xff; // LSB of block count
- command[9] = 0; // Control (reserved)
- command[10] = 0;
- command[11] = 0;
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandCommand (firstOrbID, (Ptr) command, 12);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandTimeout (firstOrbID, durationMillisecond * 100);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandFlags (firstOrbID,
- (transferIsWrite ? 0 : kSBP2CommandTransferDataFromTarget) |
- kSBP2CommandCompleteNotify);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (firstOrbID, kFWCommandSyncFlag);
-
- // Second of two transfer ORBs
- // Everything was copied into the ORB so we can recycle the arguments immediately.
- buffers[0].addressLo = 512 + (UInt32) buffer;
- command[5] = (lba+1) & 0xff; // LSB of LBA
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandBuffers (orbID, 1, buffers, lengths);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandCommand (orbID, (Ptr) command, 12);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandTimeout (orbID, durationMillisecond * 100);
-
- if (status == noErr)
- status = FWSetSBP2NormalCommandFlags (orbID,
- (transferIsWrite ? 0 : kSBP2CommandTransferDataFromTarget) |
- kSBP2CommandCompleteNotify);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (orbID, kFWCommandSyncFlag);
-
- //////////////////
- // Time for action
-
- if (status == noErr)
- status = FWAppendSBP2Command (dummyOrbID);
-
- // The Append command was synchronous. When it returns, the command has been
- // appended to the target. But the target probably has not executed the command yet.
-
- if (status == noErr)
- {
- //zzz Just wait for target to execute command. Should use notification instead.
- DelayForHardware (DurationToAbsolute (durationMillisecond * 100));
- //should have response by now
- }
-
- // Put two real ORBs on the list...
-
- if (status == noErr)
- status = FWAppendSBP2Command (firstOrbID);
-
- if (status == noErr)
- status = FWAppendSBP2Command (orbID);
-
- // Now we need to ring the doorbell to make the target wake up.
-
- if (status == noErr)
- status = FWWrite (gpFWSBP2DriverData->fwDOORBELL_ID);
-
- if (status == noErr)
- {
- //zzz Just wait for target to execute command. Should use notification instead.
- DelayForHardware (DurationToAbsolute (durationMillisecond * 100));
- //should have response by now
- }
-
- // My SYM13FW2500 does not understand the page_table_present bit, so this
- // command does not work. Probably my unit has old firmware.
-
- // This command works on the Seagate FireWire hard drive.
-
- // "buffer" was allocated on the stack. So it would be very bad to return
- // now if the ORB was still active.
-
- #define ORB_POINTER_TEST 0
-
- #if ORB_POINTER_TEST
- if (status == noErr)
- {
- FWCommandObjectID returnID;
- FWAddress ORB_POINTER;
-
- status = FWSetAsynchCommandParams
- (gpFWSBP2DriverData->readORB_POINTER_ID,
- 0, // generation - ignored
- gpFWSBP2DriverData->fetchAgent.addressHi, // addr from login response
- gpFWSBP2DriverData->fetchAgent.addressLo + 8, // + 8 to get ORB_POINTER
- (Ptr) &ORB_POINTER, // put result here
- 8, // block read
- 0, // max payload - ignored
- 8, // max retries
- 0); // no flags
-
- // We set the synchronous flag when we allocated the object, and we set the max payload
- // size to 512 already, so we're all set:
-
- if (status == noErr)
- status = FWRead (gpFWSBP2DriverData->readORB_POINTER_ID);
-
- // When I tried this, everything worked fine except the drive sent back 00000000.00000001
- // as its ORB pointer, which obviously is wrong. Forcing the result like this works:
- //ORB_POINTER.addressHi = 8;
- //ORB_POINTER.addressLo = 0;
- // This particular drive is not honoring SBP-2 9.1.4 where it says that when reaching a
- // null pointer the fetch agent should go into SUSPENDED state and the ORB_POINTER
- // register should contain the address of the ORB containing the null pointer. Oh well.
-
- sprintf (debugStr, "Read of ORB_POINTER status = %ld, result = %08lx.%08lx",
- (long) status, (long) ORB_POINTER.addressHi, (long) ORB_POINTER.addressLo);
- DebugStr ((ConstStr255Param) c2pstr (debugStr));
-
- if (status == noErr)
- status = FWGetSBP2NormalCommandObjectIDFromORB_POINTER (gpFWSBP2DriverData->loginCommandID,
- ORB_POINTER,
- &returnID);
-
- sprintf (debugStr, "Get...POINTER status = %ld, result = %08lx, real ORB ID = %08lx",
- (long) status, (long) returnID, (long) orbID);
- DebugStr ((ConstStr255Param) c2pstr (debugStr));
- }
- #endif
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoTargetReset
- //
- // This routine sends a TARGET RESET management ORB.
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoTargetReset(
- SBPTargetResetParamsPtr pSBPTargetResetParams)
- {
- FWCommandObjectID orbID;
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- orbID = gpFWSBP2DriverData->managementORBID;
-
- if (status == noErr)
- status = FWSetSBP2ManagementCommandFunction (orbID, kSBP2TargetReset);
-
- if (status == noErr)
- status = FWSetSBP2ManagementCommandCommandID (orbID, gpFWSBP2DriverData->loginCommandID);
-
- if (status == noErr)
- status = FWSetFWCommandFlags (orbID, kFWCommandSyncFlag);
-
- if (status == noErr)
- status = FWSBP2Manage (orbID);
-
- // The Manage command was synchronous. When it returns, the command has been
- // sent to the target and the target has executed the command.
-
- // SBP-2 says the fetch agent will be dead after a RESET_TARGET, so reset it too.
-
- if (status == noErr)
- status = FWWrite (gpFWSBP2DriverData->fwAGENT_RESET_ID);
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // DummyPowerNotify
- //
- // This is what a notification proc would look like (except a real one
- // would probably do something useful.
- //
-
- static OSStatus DummyPowerNotify (
- FWClientPowerNotifyParamsPtr pPowerNotifyParams,
- UInt32 *pCommandAcceptance)
- {
- // Do something useful here.
-
-
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
- return FWClientCommandIsComplete (pPowerNotifyParams->fwClientInterfaceParams.fwClientCommandID, 0);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2DoPowerTest
- //
- // This routine tests FWChangePower. This just tests that the calls work,
- // it doesn't really do anything. This should return noErr if run on a
- // Yosemite, and no real drivers are really using power.
- //
- // This routine makes only synchronous calls, so it must be called only at task
- // level.
- //
-
- static OSStatus SBP2DoPowerTest(
- SBPPowerTestParamsPtr pSBPPowerTestParams)
- {
- FWCommandObjectID powerID;
- UInt32 minVolts, reqWatts, allocWatts, flags;
- FWClientPowerNotifyProcPtr fwClientPowerNotifyProc;
- OSStatus powerStatus;
- OSStatus status;
-
- gpFWSBP2DriverData->notificationEvent = 0;
- gpFWSBP2DriverData->notificationCounter++;
- powerID = gpFWSBP2DriverData->powerChangeID;
-
- // Imagine our device wants no less than 10 Volts (100 deciVolts)
- // and 5 Watts (50 deciWatts).
-
- if (status == noErr)
- status = FWSetPowerCommandParams (powerID, 100, 50, 0, 0);
-
- if (status == noErr)
- status = FWSetFWClientPowerNotifyProc (gpFWSBP2DriverData->fwDriverID, &DummyPowerNotify);
-
- if (status == noErr)
- powerStatus = status = FWChangePower (powerID);
-
- if (status == noErr)
- status = FWGetPowerCommandParams (powerID, &minVolts, &reqWatts, &allocWatts, &flags);
-
- // Just test that the parameters survived and that we got our 5.0 Watts
- if (status == noErr)
- {
- if (minVolts != 100) status = notFoundErr;
- if (reqWatts != 50) status = notFoundErr;
- if (allocWatts != 50) status = notFoundErr;
- if (flags != 0) status = notFoundErr;
-
- }
-
- if (status == noErr)
- status = FWGetFWClientPowerNotifyProc (gpFWSBP2DriverData->fwDriverID,
- &fwClientPowerNotifyProc);
-
- // Make sure the notification proc is what we set it to be.
- if ((status == noErr) && (fwClientPowerNotifyProc != DummyPowerNotify))
- status = notFoundErr;
-
- // Give back the power if we got any
- if (powerStatus == noErr)
- {
- powerStatus = FWSetPowerCommandParams (powerID, 0, 0, 0, 0);
-
- if (powerStatus == noErr)
- powerStatus = FWChangePower (powerID);
- }
-
- // We don't actually want any notification.
- if (status == noErr)
- status = FWSetFWClientPowerNotifyProc (gpFWSBP2DriverData->fwDriverID,
- (FWClientPowerNotifyProcPtr) 0);
-
- pSBPPowerTestParams->status = status;
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBPLoginNotify
- //
- // This routine is called when a login command completes.
- //
-
- static OSStatus SBPLoginNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance)
- {
- OSStatus status;
-
- if (pFWClientSBP2NotifyParams->notificationEvent == kSBP2LoginComplete)
- {
- gpFWSBP2DriverData->login = true;
- gpFWSBP2DriverData->fetchAgent.addressHi =
- *(((UInt32 *) (pFWClientSBP2NotifyParams->loginResponse)) + 1);
- gpFWSBP2DriverData->fetchAgent.addressLo =
- *(((UInt32 *) (pFWClientSBP2NotifyParams->loginResponse)) + 2);
-
- // Now that we know the fetch agent address, finish setting up the
- // command objects for writing AGENT_RESET, and DOORBELL
-
- status = FWSetAsynchCommandParams
- (gpFWSBP2DriverData->fwAGENT_RESET_ID,
- 0, // generation - ignored
- gpFWSBP2DriverData->fetchAgent.addressHi, // addr from login response
- gpFWSBP2DriverData->fetchAgent.addressLo + 4, // + 4 to get AGENT_RESET
- (Ptr) gpFWSBP2DriverData, // any valid pointer will do
- 4, // quadlet write
- 0, // max payload - ignored
- 8, // max retries
- 0); // no flags
-
- status = FWSetAsynchCommandParams
- (gpFWSBP2DriverData->fwDOORBELL_ID,
- 0, // generation - ignored
- gpFWSBP2DriverData->fetchAgent.addressHi, // addr from login response
- gpFWSBP2DriverData->fetchAgent.addressLo + 16, // + 16 to get DOORBELL
- (Ptr) gpFWSBP2DriverData, // any valid pointer will do
- 4, // quadlet write
- 0, // max payload - ignored
- 8, // max retries
- 0); // no flags
- }
-
- if (pFWClientSBP2NotifyParams->notificationEvent == kSBP2Reconnecting)
- {
- gpFWSBP2DriverData->reconnecting = true;
- }
-
- if (pFWClientSBP2NotifyParams->notificationEvent == kSBP2ReconnectComplete)
- {
- gpFWSBP2DriverData->reconnecting = false;
- }
-
- if (pFWClientSBP2NotifyParams->notificationEvent == kSBP2ReconnectFailed)
- {
- gpFWSBP2DriverData->reconnecting = false;
- gpFWSBP2DriverData->reconnectFailed = true;
- }
-
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
- return FWClientCommandIsComplete (pFWClientSBP2NotifyParams->fwClientInterfaceParams.fwClientCommandID, 0);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBPStatusNotify
- //
- // This routine is called when an ORB generates status.
- //
-
- static OSStatus SBPStatusNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance)
- {
- gpFWSBP2DriverData->notificationCounter++;
- gpFWSBP2DriverData->notificationEvent = pFWClientSBP2NotifyParams->notificationEvent;
- gpFWSBP2DriverData->notificationLength = pFWClientSBP2NotifyParams->length;
- if ((pFWClientSBP2NotifyParams->message) && (pFWClientSBP2NotifyParams->length))
- BlockCopy (pFWClientSBP2NotifyParams->message,
- gpFWSBP2DriverData->notificationMessage,
- pFWClientSBP2NotifyParams->length);
-
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
- return FWClientCommandIsComplete (pFWClientSBP2NotifyParams->fwClientInterfaceParams.fwClientCommandID, 0);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBPUnsolicitedStatusNotify
- //
- // This routine is called when an unsolicited status is received.
- //
-
- static OSStatus SBPUnsolicitedStatusNotify(
- FWClientSBP2NotifyParamsPtr pFWClientSBP2NotifyParams,
- UInt32 *pCommandAcceptance)
- {
- gpFWSBP2DriverData->notificationCounter++;
- gpFWSBP2DriverData->notificationEvent = pFWClientSBP2NotifyParams->notificationEvent;
- gpFWSBP2DriverData->notificationLength = pFWClientSBP2NotifyParams->length;
- if ((pFWClientSBP2NotifyParams->message) && (pFWClientSBP2NotifyParams->length))
- BlockCopy (pFWClientSBP2NotifyParams->message,
- gpFWSBP2DriverData->notificationMessage,
- pFWClientSBP2NotifyParams->length);
-
-
- // Should now reset the Unsolocited Status Enabler - or else we'll never get any more.
- // This driver just receives one to prove that it can be done.
-
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
- return FWClientCommandIsComplete (pFWClientSBP2NotifyParams->fwClientInterfaceParams.fwClientCommandID, 0);
- }
-
-
- #if 0
- ////////////////////////////////////////////////////////////////////////////////
- //
- // SBP2ClientCommandCompletionProc
- //
- // This routine does generic completion of FireWire client commands that
- // make asynchronous FireWire service calls.
- //
-
- static void SBP2ClientCommandCompletionProc(
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData)
- {
- FWClientCommandIsComplete ((FWClientCommandID) completionProcData, commandStatus);
- }
- #endif
-